package com.second.app.future;


import com.second.app.thread.join.sleep_unreleaselock.A;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @Author GYZ
 * @Date 2024/2/2
 * <pre>
 *   invokeAny的使用和interrupt
 *      取得第一个完成任务的结果值，会出现2种情况：
 *          无if(Thread.currentThread.isInterrupted()代码)，已经获得第一个运行结果的值后，其他线程继续运行
 *          有if(Thread.currentThread.isInterrupted()代码)，已经获得第一个运行结果的值后，其他线程如果使用
 *             throw new InterruptException()代码则这些线程中断，虽然抛出了异常，但是main线程不能捕捉异常，如果
 *             想捕获异常，则需要在callable中使用try-catch显式进行捕获
 *
 *   >invokeAny与执行慢的任务异常
 *   >invokeAny与执行快的任务异常
 *   >invokeAny与全部任务异常
 *   >invokeAny(CollectionTasks,timeout,timeunit)超时的测试
 *   >invokeAll(CollectionTasks)全正确
 *   >invokeAll(CollectionTasks)快的正确慢的异常
 *   >invokeAll(CollectionTasks)快的异常慢的正确
 *   >invokeAll(CollectionTasks,timeout,timeunit)先慢后快
 *   >invokeAll(CollectionTasks,timeout,timeunit)先快后慢
 *   >invokeAll(CollectionTasks)全慢
 * </pre>
 */
//先慢后快 invokeAll(CollectionTasks,timeout,timeunit)：如果全部任务在指定的时间内没有完成，则出现异常。
//由运行结果，可以发现invokeAll方法出现超时后,调用future.get()方法时出现cancellationException异常
class CorrectWrongTask2Execute{
    public static void main(String[] args) {
        List<Callable<String>> callables = new ArrayList<>();
        callables.add(() -> {
            System.out.println("callable_a begin " + System.currentTimeMillis());
            for (int i = 0; i < 223456; i++) {
                Math.random();
                Math.random();
                System.out.println("callable_a " + (i + 1));
            }
            Thread.sleep(2000);
            System.out.println("callable_a end " + System.currentTimeMillis());
            return "return-a";
        });

        callables.add(() -> {
            System.out.println("callable_b begin " + System.currentTimeMillis());
            for (int i = 0; i < 10; i++) {
                Math.random();
                Math.random();
                System.out.println("callable_b " + (i + 1));
            }
            System.out.println("callable_b end " + System.currentTimeMillis());
            return "return-b";
        });
        ExecutorService executor = Executors.newCachedThreadPool();
        System.out.println("invoke begin " + System.currentTimeMillis());
        try {
            System.out.println("invoke begin " + System.currentTimeMillis());
            List<Future<String>> futures = executor.invokeAll(callables,2,TimeUnit.SECONDS);
            System.out.println("invoke end " + System.currentTimeMillis());
            for (Future<String> future : futures) {
                System.out.println("result=" + future.get() + " " + System.currentTimeMillis());
            }
            System.out.println("main end ");
        } catch (InterruptedException e) {
            System.out.println("报错了 InterruptedException ");
            e.printStackTrace();
        } catch (ExecutionException e) {
            System.out.println("报错了 ExecutionException ");
            e.printStackTrace();
        }
    }
}



//快的异常慢的正常执行，因为线程A出现异常，第一次for循环取得返回值时产生异常退出
//for循环，也就没有执行第二次for循环，所以在main线程中没有获得线程B的返回值，程序直接进入catch模块。
class  CorrectWrongTask1Execute{
    public static void main(String[] args) {
        List<Callable<String>> callables = new ArrayList<>();
        callables.add(() -> {
            System.out.println("callable_a begin " + System.currentTimeMillis());
            for (int i = 0; i < 123; i++) {
                Math.random();
                Math.random();
                Math.random();
                System.out.println("callable_a " + (i + 1));
            }
            if(1==1){
                System.out.println("a 报错了");
                throw new Exception("出现异常");
            }
            System.out.println("callable_a end " + System.currentTimeMillis());
            return "return-a";
        });

        callables.add(() -> {
            System.out.println("callable_b begin " + System.currentTimeMillis());
            for (int i = 0; i < 123456; i++) {
                Math.random();
                Math.random();
                Math.random();
                System.out.println("callable_b " + (i + 1));
            }
            System.out.println("callable_b end " + System.currentTimeMillis());
            return "return-b";
        });
        ExecutorService executor = Executors.newCachedThreadPool();
        System.out.println("invoke begin " + System.currentTimeMillis());
        try {
            List<Future<String>> futures = executor.invokeAll(callables);
            System.out.println("invoke end " + System.currentTimeMillis());
            for (Future<String> future : futures) {
                System.out.println("result=" + future.get() + " " + System.currentTimeMillis());
            }
            System.out.println("main end");
        } catch (InterruptedException e) {
            System.out.println("报错了 InterruptedException ");
            e.printStackTrace();
        } catch (ExecutionException e) {
            System.out.println("报错了 ExecutionException ");
            e.printStackTrace();
        }
    }
}

//执行任务快的正常，执行慢的任务出现异常，控制台打印了“出现异常”字符串。说明invokeAll方法对
//callable抛出去的异常是可以处理的，由于main()方法中直接进入catch语句块，所以导致main end没有打印出来
class CorrectWrongTaskExecute {
    public static void main(String[] args) {
        List<Callable<String>> callables = new ArrayList<>();
        callables.add(() -> {
            System.out.println("callable_a begin " + System.currentTimeMillis());
            for (int i = 0; i < 123456; i++) {
                Math.random();
                Math.random();
                Math.random();
                System.out.println("callable_a " + (i + 1));
            }
            System.out.println("callable_a end " + System.currentTimeMillis());
            return "return-a";
        });

        callables.add(() -> {
            System.out.println("callable_b begin " + System.currentTimeMillis());
            for (int i = 0; i < 223456; i++) {
                Math.random();
                Math.random();
                Math.random();
                System.out.println("callable_b " + (i + 1));
            }
            System.out.println("callable_b end " + System.currentTimeMillis());
            if(1==1){
                System.out.println("B 报错了");
                throw new Exception("出现异常");
            }
            return "return-b";
        });
        ExecutorService executor = Executors.newCachedThreadPool();
        System.out.println("invoke begin " + System.currentTimeMillis());
        try {
            List<Future<String>> futures = executor.invokeAll(callables);
            System.out.println("invoke end " + System.currentTimeMillis());
            for (Future<String> future : futures) {
                System.out.println("result=" + future.get() + " " + System.currentTimeMillis());
            }
            System.out.println("main end");
        } catch (InterruptedException e) {
            System.out.println("报错了 InterruptedException ");
            e.printStackTrace();
        } catch (ExecutionException e) {
            System.out.println("报错了 ExecutionException ");
            e.printStackTrace();
        }
    }
}


//invokeAll(CollectionTasks)全正确
class CorrectTaskExecute {
    public static void main(String[] args) {
        List<Callable<String>> callables = new ArrayList<>();
        callables.add(() -> {
            System.out.println(Thread.currentThread().getName() + " begin " + System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println(Thread.currentThread().getName() + " end " + System.currentTimeMillis());
            return "return-a";
        });

        callables.add(() -> {
            System.out.println(Thread.currentThread().getName() + " begin " + System.currentTimeMillis());
            Thread.sleep(8000);
            System.out.println(Thread.currentThread().getName() + " end " + System.currentTimeMillis());
            return "return-b";
        });
        ExecutorService executor = Executors.newCachedThreadPool();
        System.out.println("invoke begin " + System.currentTimeMillis());
        try {
            List<Future<String>> futures = executor.invokeAll(callables);
            System.out.println("invoke end " + System.currentTimeMillis());
            for (Future<String> future : futures) {
                System.out.println("返回的结果=" + future.get() + " " + System.currentTimeMillis());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
    //方法invokeAll()执行的时间为8s，由此可见阻塞性。
}

class TimeOutTaskException {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        List<Callable<String>> callables = new ArrayList<>();
        callables.add(() -> {
            System.out.println("begin:" + System.currentTimeMillis());
            for (int i = 0; i < 193456; i++) {
                Math.random();
                Math.random();
                Math.random();
                Math.random();
                Math.random();
                Math.random();
                Math.random();
                Math.random();
                Math.random();
                Math.random();
                System.out.println("Thread name:" + Thread.currentThread().getName() + ":" + (i + 1));
            }
            Thread.sleep(2000);
            System.out.println("end:" + System.currentTimeMillis());
            return "customValue";
        });
        try {
            String value = executor.invokeAny(callables, 1, TimeUnit.SECONDS);
            System.out.println("===========" + value);
            System.out.println("zzzzzzzzzzzzzzzzz");
        } catch (InterruptedException e) {
            System.out.println("进入 catch InterruptedException ");
            e.printStackTrace();
        } catch (ExecutionException e) {
            System.out.println("进入 catch ExecutionException ");
            e.printStackTrace();
        } catch (TimeoutException e) {
            System.out.println("进入 catch timeOutException 超时了");
            e.printStackTrace();
        }
    }
}


//invokeAny与全部任务异常，都出现异常时，会返回最后一个异常并输出
class AllTaskException {
    public static void main(String[] args) {
        List<Callable<String>> callables = new ArrayList<>();
        callables.add(() -> {
            for (int i = 0; i < 123456; i++) {
                Math.random();
                Math.random();
                Math.random();
//                System.out.println("myCallableA " + (i + 1));
            }
            System.out.println("myCallableA end " + System.currentTimeMillis());
            if (1 == 1) {
                System.out.println("1==1");
                throw new Exception("报错了AAAAAA");
            }
            return "return_a";
        });
        callables.add(() -> {
            for (int i = 0; i < 123456; i++) {
                Math.random();
                Math.random();
                Math.random();
//                System.out.println("myCallableB " + (i + 1));
            }
            System.out.println("myCallableB end " + System.currentTimeMillis());
            if (1 == 1) {
                System.out.println("1==1");
                throw new Exception("报错了 BBBBBB");
            }
            return "return_b";
        });

        ExecutorService executor = Executors.newCachedThreadPool();
        try {
            String result = executor.invokeAny(callables);
            System.out.println("返回值= " + result);
            System.out.println("main end ");
        } catch (InterruptedException | ExecutionException e) {
            System.out.println("进入 catch exception了");
            e.printStackTrace();
        }
    }
}

//invokeAny与执行快的任务异常
class Quick1Callable implements Callable<String> {
    @Override
    public String call() throws Exception {
        System.out.println("Quick1Callable " + Thread.currentThread().getName() + "begin " + System.currentTimeMillis());
        for (int i = 0; i < 123456; i++) {
            String newString = new String();
            Math.random();
            Math.random();
            Math.random();
            Math.random();
            Math.random();
        }
        System.out.println("Quick1Callable " + Thread.currentThread().getName() + "end " + System.currentTimeMillis());
        return "return-a";
    }
}

class Quick2Callable implements Callable<String> {
    @Override
    public String call() throws Exception {
        System.out.println("Quick2Callable " + Thread.currentThread().getName() + "begin " + System.currentTimeMillis());
        for (int i = 0; i < 123456; i++) {
            String newString = new String();
            Math.random();
            Math.random();
            Math.random();
            Math.random();
            Math.random();
        }
        if (1 == 1) {
            System.out.println("xxxxxxxxxx= 中断了");
            throw new NullPointerException();
        }

//        try {
//            if (1 == 1) {
//                System.out.println("xxxxxxxxxx= 中断了");
//                throw new NullPointerException();
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//            System.out.println(e.getMessage()+" 通过显式try-catch 捕获异常了");
//        }
        System.out.println("Quick2Callable " + Thread.currentThread().getName() + "end " + System.currentTimeMillis());
        return "return-a";
    }
}

class InvokeTaskQuickly {
    public static void main(String[] args) {
        List<Callable<String>> callables = new ArrayList<>();
        callables.add(new Quick2Callable());
        callables.add(new Quick1Callable());
        ExecutorService executor = Executors.newCachedThreadPool();
        try {
            String result = executor.invokeAny(callables);
            System.out.println("main取得的返回值= " + result);
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }
    }
}

//invokeAny与执行慢的任务异常
class Slow1Callable implements Callable<String> {
    @Override
    public String call() throws Exception {
        System.out.println("Slow1Callable " + Thread.currentThread().getName() + "begin " + System.currentTimeMillis());
        for (int i = 0; i < 193456; i++) {
            String newString = new String();
            Math.random();
            Math.random();
            Math.random();
            Math.random();
            Math.random();
        }
        System.out.println("SlowCallable " + Thread.currentThread().getName() + "end " + System.currentTimeMillis());
        return "return-a";
    }
}

class Slow2Callable implements Callable<String> {
    @Override
    public String call() throws Exception {
        System.out.println("Slow2Callable " + Thread.currentThread().getName() + "begin " + System.currentTimeMillis());
        for (int i = 0; i < 123456; i++) {
            String newString = new String();
            Math.random();
            Math.random();
            Math.random();
            Math.random();
            Math.random();
        }
//        if (1 == 1) {
//            System.out.println("xxxxxxxxxx= 中断了");
//            throw new NullPointerException();
//        }

        try {
            if (1 == 1) {
                System.out.println("xxxxxxxxxx= 中断了");
                throw new NullPointerException();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage() + " 通过显式try-catch 捕获异常了");
        }
        System.out.println("Slow2Callable " + Thread.currentThread().getName() + "end " + System.currentTimeMillis());
        return "return-a";
    }
}


class RunDemo123 {
    public static void main(String[] args) {
        List<Callable<String>> callables = new ArrayList<>();
        callables.add(new Slow1Callable());
        callables.add(new Slow2Callable());
        ExecutorService executor = Executors.newCachedThreadPool();
        try {
            String result = executor.invokeAny(callables);
            System.out.println("result: " + result);
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }
        //从输出结果来看：成功取得return-a字符串，但是另外一个线程中断了，但是抛出的空指针异常么有在控制台输出
        //如果想要在callables中捕获异常信息，则需要显式的添加try-catch语句块
    }
}

public class ExecutorServiceRun {

    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        List<Callable<String>> callables = new ArrayList<>();

        callables.add(() -> {
            for (int i = 0; i < 123456; i++) {
                Math.random();
                Math.random();
                Math.random();
                System.out.println("myCallableA " + (i + 1));
            }
            System.out.println("myCallableA end " + System.currentTimeMillis());
            return "return_a";
        });
        callables.add(() -> {
            for (int i = 0; i < 223456; i++) {
                Math.random();
                Math.random();
                Math.random();
                System.out.println("myCallableB " + (i + 1));
            }
            System.out.println("myCallableB  end " + System.currentTimeMillis());
            return "return_b";
        });
        try {
            String value = executor.invokeAny(callables);
            System.out.println("=========================" + value);
            System.out.println("zzzzzzzzzzzzzzzzzzzzzzzz");
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }
    }
    //invokeAny()已经取得return_a的值，但是另外一个线程B还在继续运行中。
}
